package com.cl.auth.stateless;

import com.cl.auth.AuthService;
import com.cl.util.Constants;

import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

/**
 * 根据token校验用户的filter
 */
public class StatelessAuthcFilter extends AccessControlFilter {

    private static final String ACCESS_TOKEN = "accessToken";

    private static final Logger LOGGER = LoggerFactory.getLogger(StatelessAuthcFilter.class);

    @Autowired
    private AuthService authService;

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        return false;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse response) throws Exception {
        String accessToken = getAccessTokenByRequest(servletRequest);
        // 生成无状态Token
        StatelessToken token = new StatelessToken(accessToken, true);
        try {
            // 委托给Realm进行登录
            getSubject(servletRequest, response).login(token);
        } catch (Exception e) {
            LOGGER.error("Access Denied : {}", accessToken);
            onLoginFail(response);
            return false;
        }
//        //c4w 先判断缓存中是否包含user信息
//        StatelessUser user = (StatelessUser)RequestContextHolder.currentRequestAttributes().getAttribute(Constants.USER_KEY, RequestAttributes.SCOPE_SESSION);
//        if(user==null){
//            user = authService.getUser(accessToken);
//            RequestContextHolder.currentRequestAttributes().setAttribute(Constants.USER_KEY, user, RequestAttributes.SCOPE_SESSION);        	
//        }
        return true;
    }

    /**
     * 校验失败，返回401状态码
     *
    * @param response ServletResponse
    * @throws IOException IOException
    */
    private void onLoginFail(ServletResponse response) throws IOException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        httpResponse.getWriter().write("Invalid Token!");
    }

    private String getAccessTokenByRequest(ServletRequest servletRequest) {
        String accessToken = servletRequest.getParameter(ACCESS_TOKEN);
        if (accessToken == null || "".equals(accessToken) ) {
            if (servletRequest instanceof ShiroHttpServletRequest){
                accessToken = getCookieValueByKey(((ShiroHttpServletRequest)servletRequest).getCookies(), ACCESS_TOKEN);
            }
        }
        return accessToken;
    }

    private String getCookieValueByKey(Cookie[] cookies, String key) {
        String val = null;
        for(Cookie cookie:cookies) {
            if(cookie != null && key.equals(cookie.getName())) {
                val = cookie.getValue();
                break;
            }
        }
        return val;
    }

}